package com.battle.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.battle.pojo.entity.*;
import com.battle.pojo.enums.OrganizationTypeEnum;
import com.battle.pojo.param.trainingGroup.GetTrainingDataParam;
import com.battle.pojo.param.trainingGroup.GetTrainingGroupNumberListParam;
import com.battle.pojo.param.trainingGroup.GetTrainingNumberListParam;
import com.battle.pojo.param.trainingGroup.GetTrainingSoleNumberListParam;
import com.battle.pojo.param.trainingProgram.*;
import com.battle.pojo.vo.trainingGroup.*;
import com.battle.pojo.vo.trainingProgram.*;
import com.battle.pojo.dto.trainingProgram.*;
import com.battle.service.repository.in.*;
import com.battle.service.service.in.TrainingProgramService;
import lombok.AllArgsConstructor;
import nirvana.core.domains.vo.PageResult;
import nirvana.core.utils.ids.IdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.propertyeditors.LocaleEditor;
import org.springframework.stereotype.Service;


import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 【描 述】：训练项目服务
 * 【环 境】：J2SE 17·
 * 【详 细】：
 */
@Service
@AllArgsConstructor
public class TrainingProgramServiceImpl implements TrainingProgramService {

    private final TrainingProgramRepository trainingProgramRepository;
    private final UserRepository userRepository;
    private final OrganizationRepository organizationRepository;
    private final TrainingGroupRepository groupRepository;
    private final TrainingSoloRepository soloRepository;
    private final TrainingSoloDetailsRepository soloDetailsRepository;
    private final UserOrganizationMpRepository userOrganizationMpRepository;


    /**
     * 创建训练项目
     *
     * @param param
     */
    @Override
    public void createTrainingProgram(CreateTrainingProgramParam param) {
        TrainingProgram trainingProgram = new TrainingProgram();
        BeanUtils.copyProperties(param, trainingProgram);
        Long id = IdGenerator.SNOW.generate();
        trainingProgram.setId(id);

        if (param.getManScore() != null) {
            trainingProgram.setManScore(JSONObject.toJSONString(param.getManScore()));
        }
        if (param.getGirlScore() != null) {
            trainingProgram.setGirlScore(JSONObject.toJSONString(param.getGirlScore()));
        }
        if (param.getStandard() != null) {
            trainingProgram.setStandard(JSONArray.toJSONString(param.getStandard()));
        }
        if (param.getJudgeDetail() != null) {
            trainingProgram.setJudgeDetail(JSONArray.toJSONString(param.getJudgeDetail()));
        }
        if (param.getGroupScore() != null) {
            trainingProgram.setGroupScore(JSONArray.toJSONString(param.getGroupScore()));
        }

        trainingProgramRepository.create(trainingProgram);
    }

    /**
     * 修改训练项目
     *
     * @param param
     */
    @Override
    public void editTrainingProgram(EditTrainingProgramParam param) {
        Long id = param.getId();
        TrainingProgram trainingProgram = trainingProgramRepository.getByIdCheck(id);
        BeanUtils.copyProperties(param, trainingProgram);

        if (param.getManScore() != null) {
            trainingProgram.setManScore(JSONObject.toJSONString(param.getManScore()));
        }
        if (param.getGirlScore() != null) {
            trainingProgram.setGirlScore(JSONObject.toJSONString(param.getGirlScore()));
        }
        if (param.getStandard() != null) {
            trainingProgram.setStandard(JSONArray.toJSONString(param.getStandard()));
        }
        if (param.getJudgeDetail() != null) {
            trainingProgram.setJudgeDetail(JSONArray.toJSONString(param.getJudgeDetail()));
        }
        if (param.getGroupScore() != null) {
            trainingProgram.setGroupScore(JSONArray.toJSONString(param.getGroupScore()));
        }
        trainingProgramRepository.edit(trainingProgram);
    }

    /**
     * 移除训练项目
     *
     * @param id
     */
    @Override
    public void removeTrainingProgram(Long id) {
        trainingProgramRepository.removeById(id);
    }

    /**
     * 启动/禁用训练项目
     *
     * @param id
     */
    @Override
    public void enabledTrainingProgram(Long id) {
        TrainingProgram trainingProgram = trainingProgramRepository.getByIdCheck(id);
        trainingProgram.setIsDisable(!trainingProgram.getIsDisable());
        trainingProgramRepository.edit(trainingProgram);
    }

    /**
     * 获取训练项目详情
     *
     * @param id
     * @return
     */
    @Override
    public GetTrainingProgramVo getTrainingProgram(Long id) {
        TrainingProgram trainingProgram = trainingProgramRepository.getByIdCheck(id);
        GetTrainingProgramVo vo = new GetTrainingProgramVo();
        BeanUtils.copyProperties(trainingProgram, vo);
        vo.setEnabled(!trainingProgram.getIsDisable());

        if (trainingProgram.getManScore() != null) {
            vo.setManScore(JSONObject.parseObject(trainingProgram.getManScore(), SexScoreJsonParam.class));
        }
        if (trainingProgram.getGirlScore() != null) {
            vo.setGirlScore(JSONObject.parseObject(trainingProgram.getGirlScore(), SexScoreJsonParam.class));
        }
        if (trainingProgram.getStandard() != null) {
            vo.setStandard(JSONArray.parseArray(trainingProgram.getStandard(), StandardJsonParam.class));
        }
        if (trainingProgram.getJudgeDetail() != null) {
            vo.setJudgeDetail(JSONArray.parseArray(trainingProgram.getJudgeDetail(), JudgeDetailJsonParam.class));
        }
        if (trainingProgram.getGroupScore() != null) {
            vo.setGroupScore(JSONArray.parseArray(trainingProgram.getGroupScore(), GroupScoreJsonParam.class));
        }
        //提交人
        User user = userRepository.getById(trainingProgram.getUpdater());
        if (user != null) {
            vo.setUpdateName(user.getName());
        }
        return vo;
    }

    /**
     * 获取训练项目 列表
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<GetTrainingProgramListVo> getTrainingProgramList(GetTrainingProgramListParam param) {

        SelectTrainingProgramDto dto = new SelectTrainingProgramDto();
        BeanUtils.copyProperties(param, dto);
        Page<TrainingProgram> page = trainingProgramRepository.selectTrainingProgram(dto);
        List<TrainingProgram> trainingProgramList = page.getRecords();
        List<GetTrainingProgramListVo> list = new ArrayList<>();

        if (CollectionUtil.isNotEmpty(trainingProgramList)) {
            List<Long> userIds = new ArrayList<>();
            trainingProgramList.forEach(v -> {
                userIds.add(v.getUpdater());
            });

            Map<Long, User> userMap = userRepository.getMap(userIds);

            for (TrainingProgram trainingProgram : trainingProgramList) {
                GetTrainingProgramListVo vo = new GetTrainingProgramListVo();
                BeanUtils.copyProperties(trainingProgram, vo);

                User submit = userMap.get(trainingProgram.getUpdater());
                if (submit != null) {
                    vo.setUpdateName(submit.getName());
                }

                vo.setEnabled(!trainingProgram.getIsDisable());
                list.add(vo);
            }
        }

        return new PageResult<>(list, page);

    }

    /**
     * 获取训练项目下拉列表
     *
     * @param param
     * @return
     */
    @Override
    public List<GetTrainingProgramDownListVo> getTrainingProgramDownList(GetTrainingProgramDownListParam param) {
        TrainingProgram po = new TrainingProgram();
        if (param != null) {
            BeanUtils.copyProperties(param, po);
        }
        List<TrainingProgram> trainingProgramList = trainingProgramRepository.getListByEntity(po);

        List<GetTrainingProgramDownListVo> list = new ArrayList<>();
        for (TrainingProgram trainingProgram : trainingProgramList) {
            GetTrainingProgramDownListVo vo = new GetTrainingProgramDownListVo();
            BeanUtils.copyProperties(trainingProgram, vo);
            list.add(vo);
        }
        return list;
    }

    @Override
    public List<GetTrainingNumberVo> getTrainingNumberList(GetTrainingNumberListParam param) {
        List<GetTrainingNumberVo> voList = new ArrayList<>();

        Organization organization = new Organization();
        if (param.getParentOrganizationId() == null) {
            organization.setType(OrganizationTypeEnum.detachment);
        } else {
            organization.setParentId(param.getParentOrganizationId());
            organization.setType(OrganizationTypeEnum.big_detachment);
        }
        List<Organization> organizationList = organizationRepository.getListByEntity(organization);
        if (CollectionUtil.isNotEmpty(organizationList)) {
            for (Organization dept : organizationList) {
                GetTrainingNumberVo vo = new GetTrainingNumberVo();
                vo.setId(dept.getId());
                vo.setOrganizationName(dept.getName());
                //年度训练总量
                Integer yearTrainingNumber = 0;

                //获取该组织架构下所有的组织架构
                List<Long> ids = organizationRepository.getOrganizationIdList(dept.getId());

                //根据时间查询这个单位下的小组训练量
                Integer groupTrainingNumber = 0;
                List<TrainingGroup> trainingGroups = groupRepository.selectGroupByPath(ids, param.getStartTime(), param.getEndTime(), null);
                if (CollectionUtil.isNotEmpty(trainingGroups)) {
                    groupTrainingNumber = trainingGroups.size();
                }

                //根据时间查询这个单位下的个人训练量
                Integer soloTrainingNumber = 0;
                List<TrainingSolo> trainingSolos = soloRepository.selectSoleByPath(ids, param.getStartTime(), param.getEndTime());
                if (CollectionUtil.isNotEmpty(trainingSolos)) {
                    soloTrainingNumber = trainingSolos.size();
                }

                yearTrainingNumber = groupTrainingNumber + soloTrainingNumber;

                vo.setAnnualTrainingTotal(yearTrainingNumber);
                vo.setGroupTrainingTotal(groupTrainingNumber);
                vo.setSoloTrainingTotal(soloTrainingNumber);
                voList.add(vo);
            }
        }

        if (param.getSortType() == null) param.setSortType(0);

        if (CollectionUtil.isNotEmpty(voList)) {
            //判断需要按照什么排序规则排序
            if (param.getSortType() == 0) {
                //根据训练总量倒叙排序
                voList = voList.stream().sorted(Comparator.comparing(GetTrainingNumberVo::getAnnualTrainingTotal).reversed()).collect(Collectors.toList());
            } else if (param.getSortType() == 1) {
                //根据小组训练量倒叙排序
                voList = voList.stream().sorted(Comparator.comparing(GetTrainingNumberVo::getGroupTrainingTotal).reversed()).collect(Collectors.toList());
            } else if (param.getSortType() == 2) {
                //根据个人训练量倒叙排序
                voList = voList.stream().sorted(Comparator.comparing(GetTrainingNumberVo::getSoloTrainingTotal).reversed()).collect(Collectors.toList());
            }
        }
        return voList;
    }

    @Override
    public List<GetTrainingGroupNumberVo> getTrainingGroupNumberList(GetTrainingGroupNumberListParam param) {
        List<GetTrainingGroupNumberVo> voList = new ArrayList<>();

        Organization organization = new Organization();
        if (param.getParentOrganizationId() == null) {
            organization.setType(OrganizationTypeEnum.detachment);
        } else {
            organization.setParentId(param.getParentOrganizationId());
            organization.setType(OrganizationTypeEnum.big_detachment);
        }

        //选择的日期年份数据
        LocalDate yearStartTime = LocalDate.of(param.getStartTime().getYear(), 1, 1);
        LocalDate yearEndTime = LocalDate.of(param.getStartTime().getYear(), 12, 31);
        LocalDate startTime = param.getStartTime();
        LocalDate endTime = param.getEndTime();

        List<Organization> organizationList = organizationRepository.getListByEntity(organization);
        if (CollectionUtil.isEmpty(organizationList)) {
            return voList;
        }
        if (CollectionUtil.isNotEmpty(organizationList)) {
            for (Organization dept : organizationList) {
                GetTrainingGroupNumberVo vo = new GetTrainingGroupNumberVo();
                vo.setId(dept.getId());
                vo.setOrganizationName(dept.getName());

                //获取该组织架构下所有的组织架构
                List<Long> ids = organizationRepository.getOrganizationIdList(dept.getId());

                //年度训练总量
                Integer yearTrainingNumber = 0;

                List<TrainingGroup> trainingGroups = groupRepository.selectGroupByPath(ids, yearStartTime, yearEndTime, param.getTrainingProgramId());
                if (CollectionUtil.isNotEmpty(trainingGroups)) {
                    yearTrainingNumber = yearTrainingNumber + trainingGroups.size();
                }
                List<TrainingSoloDetails> detailsList = soloDetailsRepository.selectSoleDetailsByPath(ids, yearStartTime, yearEndTime, param.getTrainingProgramId());
                if (CollectionUtil.isNotEmpty(detailsList)) {
                    yearTrainingNumber = yearTrainingNumber + detailsList.size();
                }

                //月度训练总量
                Integer monthTrainingNumber = 0;
                trainingGroups = groupRepository.selectGroupByPath(ids, startTime, endTime, param.getTrainingProgramId());
                if (CollectionUtil.isNotEmpty(trainingGroups)) {
                    monthTrainingNumber = monthTrainingNumber + trainingGroups.size();
                }
                detailsList = soloDetailsRepository.selectSoleDetailsByPath(ids, startTime, endTime, param.getTrainingProgramId());
                if (CollectionUtil.isNotEmpty(detailsList)) {
                    monthTrainingNumber = monthTrainingNumber + detailsList.size();
                }

                vo.setAnnualTrainingTotal(yearTrainingNumber);
                vo.setMonthlyTrainingTotal(monthTrainingNumber);
                voList.add(vo);
            }
        }

        if (param.getSortType() == null) param.setSortType(0);

        if (CollectionUtil.isNotEmpty(voList)) {
            //判断需要按照什么排序规则排序
            if (param.getSortType() == 0) {
                //根据训练总量倒叙排序
                voList = voList.stream().sorted(Comparator.comparing(GetTrainingGroupNumberVo::getAnnualTrainingTotal).reversed()).collect(Collectors.toList());
            } else if (param.getSortType() == 1) {
                //根据小组训练量倒叙排序
                voList = voList.stream().sorted(Comparator.comparing(GetTrainingGroupNumberVo::getMonthlyTrainingTotal).reversed()).collect(Collectors.toList());
            }
        }

        return voList;
    }

    @Override
    public List<GetTrainingSoleNumberVo> getTrainingSoleNumberList(GetTrainingSoleNumberListParam param) {
        List<GetTrainingSoleNumberVo> voList = new ArrayList<>();


        List<TrainingSoloDetails> detailsList = new ArrayList<>();
        if (param.getOrganizationId() != null) {
            List<Long> ids = organizationRepository.getOrganizationIdList(param.getOrganizationId());
            detailsList = soloDetailsRepository.selectSoleDetailsByPath(ids, param.getStartTime(), param.getEndTime(), param.getTrainingProgramId());
        } else {
            detailsList = soloDetailsRepository.selectSoleDetailsByPath(null, param.getStartTime(), param.getEndTime(), param.getTrainingProgramId());
        }

        if (CollectionUtil.isNotEmpty(detailsList)) {
            Map<Long, List<TrainingSoloDetails>> listMap = detailsList.stream().collect(Collectors.groupingBy(TrainingSoloDetails::getUserId));

            //提取出用户的ids
            List<Long> userIds = detailsList.stream().map(TrainingSoloDetails::getUserId).collect(Collectors.toList());
            //根据用户ids查询用户信息
            List<User> userList = userRepository.listByIds(userIds);

            for (User user : userList) {
                GetTrainingSoleNumberVo vo = new GetTrainingSoleNumberVo();
                vo.setId(user.getId());
                vo.setUserName(user.getName());

                //组织架构id
                UserOrganizationMp entity = new UserOrganizationMp();
                entity.setUserId(user.getId());
                entity.setIsDelete(false);
                List<UserOrganizationMp> userOrganizationList = userOrganizationMpRepository.getListByEntity(entity);
                if (CollectionUtil.isNotEmpty(userOrganizationList)) {
                    List<Long> organizationIds = userOrganizationList.stream().map(UserOrganizationMp::getOrganizationId).collect(Collectors.toList());
                    List<Organization> organizationList = organizationRepository.getListByIds(organizationIds);
                    if (CollectionUtil.isNotEmpty(organizationList)) {
                        List<String> organizationNames = organizationList.stream().map(Organization::getName).collect(Collectors.toList());
                        String organizationName = String.join(",", organizationNames);
                        vo.setOrganizationName(organizationName);
                    }
                }


                //训练总量
                Integer totalTrainingNumber = 0;

                //参训量
                Integer trainingNumber = 0;
                List<TrainingSoloDetails> soloDetails = listMap.get(user.getId());
                if (CollectionUtil.isNotEmpty(soloDetails)) {
                    trainingNumber = soloDetails.size();
                }

                //缺训量
                Integer lackTrainingNumber = 0;
                List<TrainingSolo> trainingSolos = soloRepository.selectAbsentPersonUserIds(user.getId().toString(), param.getStartTime(), param.getEndTime());
                if (CollectionUtil.isNotEmpty(trainingSolos)) {
                    lackTrainingNumber = trainingSolos.size();
                }

                totalTrainingNumber = trainingNumber + lackTrainingNumber;

                vo.setTotalTrainingNumber(totalTrainingNumber);
                vo.setTrainingNumber(trainingNumber);
                vo.setLackTrainingNumber(lackTrainingNumber);
                voList.add(vo);
            }
        }

        if (param.getSortType() == null) param.setSortType(0);

        if (CollectionUtil.isNotEmpty(voList)) {
            //判断需要按照什么排序规则排序
            if (param.getSortType() == 0) {
                //根据训练总量倒叙排序
                voList = voList.stream().sorted(Comparator.comparing(GetTrainingSoleNumberVo::getTotalTrainingNumber).reversed()).collect(Collectors.toList());
            } else if (param.getSortType() == 1) {
                //根据小组训练量倒叙排序
                voList = voList.stream().sorted(Comparator.comparing(GetTrainingSoleNumberVo::getTrainingNumber).reversed()).collect(Collectors.toList());
            } else if (param.getSortType() == 2) {
                //根据小组训练量倒叙排序
                voList = voList.stream().sorted(Comparator.comparing(GetTrainingSoleNumberVo::getLackTrainingNumber).reversed()).collect(Collectors.toList());
            }
        }
        return voList;
    }

    /**
     * 获取训练数据统计图
     *
     * @param param
     * @return
     */
    @Override
    public GetTrainingDataVo getTrainingDataVo(GetTrainingDataParam param) {
        GetTrainingDataVo dataVo = new GetTrainingDataVo();

        List<GetTrainingDataDetailsListVo> list = new ArrayList<>();

        Organization organizationSelect = new Organization();
        if (param.getParentOrganizationId() == null) {
            organizationSelect.setType(OrganizationTypeEnum.detachment);
        } else {
            organizationSelect.setParentId(param.getParentOrganizationId());
            organizationSelect.setType(OrganizationTypeEnum.big_detachment);
        }
        List<Organization> organizationList = organizationRepository.getListByEntity(organizationSelect);

        if (CollectionUtil.isEmpty(organizationList)) {
            return dataVo;
        }

        for (Organization organization : organizationList) {
            //获取该组织架构下所有的组织架构
            List<Long> ids = organizationRepository.getOrganizationIdList(organization.getId());

            //小组训练
            if (param.getType() == 0 || param.getType() == 2) {
                List<TrainingGroup> trainingGroups = groupRepository.selectGroupByPath(ids, param.getStartTime(), param.getEndTime(), null);
                if (CollectionUtil.isNotEmpty(trainingGroups)) {
                    for (TrainingGroup group : trainingGroups) {
                        GetTrainingDataDetailsListVo vo = new GetTrainingDataDetailsListVo();
                        vo.setId(group.getId());
                        vo.setOrganizationId(group.getDepartmentId());
                        vo.setMonth(group.getTrainingDate().getMonthValue());
                        list.add(vo);
                    }
                }
            }
            //单人训练量
            if (param.getType() == 1 || param.getType() == 2) {
                List<TrainingSolo> trainingSolos = soloRepository.selectSoleByPath(ids, param.getStartTime(), param.getEndTime());
                if (param.getType() == 1 || param.getType() == 2) {
                    if (CollectionUtil.isNotEmpty(trainingSolos)) {
                        for (TrainingSolo group : trainingSolos) {
                            GetTrainingDataDetailsListVo vo = new GetTrainingDataDetailsListVo();
                            vo.setId(group.getId());
                            vo.setOrganizationId(group.getDepartmentId());
                            vo.setMonth(group.getTrainingDate().getMonthValue());
                            list.add(vo);
                        }
                    }
                }
            }
        }


        if (CollectionUtil.isEmpty(list)) {
            return dataVo;
        }


        //月份=固定12个月
        List<Integer> monthList = new ArrayList<>();
        for (int i = 1; i <= 12; i++) {
            monthList.add(i);
        }

        List<GetTrainingDataDetailsVo> itemList = new ArrayList<>();
        for (Organization organization : organizationList) {
            GetTrainingDataDetailsVo vo = new GetTrainingDataDetailsVo();
            vo.setOrganizationName(organization.getName());
            vo.setOrganizationId(organization.getId());

            List<Integer> valueList = new ArrayList<>();
            for (Integer month : monthList) {
                int count = 0;
                for (GetTrainingDataDetailsListVo item : list) {
                    if (item.getOrganizationId().equals(organization.getId()) && item.getMonth().equals(month)) {
                        count++;
                    }
                }
                valueList.add(count);
            }
            vo.setValueList(valueList);
            itemList.add(vo);
        }

        dataVo.setMonthList(monthList);
        dataVo.setItemList(itemList);
        return dataVo;
    }
}



